package com.example.demo.main.stream;

import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.lang.Character.isDigit;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summingDouble;
import static java.util.stream.Collectors.toList;

/**
 * @author xieluoyin
 */
class A {
    @Test
    void collect() {
        List<String> collected = Stream.of("a", "b", "c")
                .collect(toList());
        System.out.println();
    }

    @Test
    void map() {

        List<String> collected = Stream.of("a", "b", "hello")
                .map(String::toUpperCase)
                .collect(toList());
        System.out.println();

    }

    @Test
    void filter() {
        List<String> beginningWithNumbers
                = Stream.of("a", "1abc", "abc1")
                .filter(value -> isDigit(value.charAt(0)))
                .collect(toList());
        System.out.println();
    }

    @Test
    void flatMap() {
        List<Integer> together = Stream.of(asList(1, 2), asList(3, 4))
                .flatMap(Collection::stream)
                .collect(toList());
        System.out.println();
    }

    @Test
    void min() {
//        List<MyBean> myBeans = asList(new MyBean("Bakai", new Date(104L)),
//                new MyBean("Violets for Your Furs", new Date(95L)),
//                new MyBean("Time Was", new Date(56L)));
//        MyBean myBean = new MyBean("csdc", new Date());
//        MyBean oldestBean = myBeans.stream()
//                .min(Comparator.comparing(MyBean::getCreateDate))
//                .orElse(myBean);
//        System.out.println();
    }

    @Test
    void reduce() {
        int count = Stream.of(1, 2, 3)
                .reduce(0, (acc, element) -> acc + element);
        System.out.println();
    }

    @Test
    void intSummaryStatistics() {
        Album album = new Album();
        IntSummaryStatistics trackLengthStats
                = album.getTracks().stream()
                .mapToInt(Track::getLength)
                .summaryStatistics();
        System.out.printf("Max: %d, Min: %d, Ave: %f, Sum: %d",
                trackLengthStats.getMax(),
                trackLengthStats.getMin(),
                trackLengthStats.getAverage(),
                trackLengthStats.getSum());
    }

    @Test
    void parallel() {
        Map map = parallelDiceRolls();
        System.out.println();
    }

    Map<Integer, Double> parallelDiceRolls() {
        int n1 = 1000;
        double fraction = 1.0 / n1;
        return IntStream.range(0, n1)
                .parallel()
                .mapToObj(i ->
                        twoDiceThrows()
                )
                .collect(groupingBy(side -> side,
                        summingDouble(n -> fraction)));
    }

    private static int twoDiceThrows() {
        ThreadLocalRandom random = ThreadLocalRandom.current();
        int firstThrow = random.nextInt(1, 7);
        int secondThrow = random.nextInt(1, 7);
        return firstThrow + secondThrow;
    }

    /**
     * 并行化数组操作
     * @param size
     * @return
     */
    public static double[] parallelInitialize(int size) {
        double[] values = new double[size];
        Arrays.parallelSetAll(values, i -> i);
        return values;
    }
    @Test
    void simpleMovingAverage(){
        double[] d=simpleMovingAverage(new double[]{0.0, 1.0, 2.0, 3.0, 4.0, 3.5},3);
        System.out.println();
    }

    /**
     *
     * @param values
     * @param n 滑动窗口大小
     * @return
     */
    private static double[] simpleMovingAverage(double[] values, int n) {
        double[] sums = Arrays.copyOf(values, values.length);
        Arrays.parallelPrefix(sums, Double::sum);
        int start = n - 1;
        return IntStream.range(start, sums.length)
                    .mapToDouble(i -> {
            double prefix = i == start ? 0 : sums[i - n];
            return (sums[i] - prefix) / n;
        })
                .toArray();
    }
    public long countTracks(List<Album> albums) {
        return albums.stream()
                .mapToLong(album -> album.getTracks().size())
                .sum();
    }
    private boolean isPrime(int number) {
        return IntStream.range(2, number)
                .allMatch(x -> (number % x) != 0);
    }
}
